﻿#region 참조 네임스페이스

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;

#endregion

namespace Skying.Net.NetworkInformation
{
	/// <summary>
	/// <see cref="System.Net.NetworkInformation"/> 네임스페이스에 대한 랩핑 메서드들을 제공한다.
	/// </summary>
	public static class NetworkInformation
	{
		/// <summary>
		/// 네트워크에 연결되어 사용 가능한 네트워크 인터페이스의 IP 주소를 가져온다.
		/// </summary>
		/// <param name="activeAddress">네트워크에 연결되어 사용 가능한 네트워크 인터페이스의 IP 주소 참조를 설정한다.</param>
		/// <returns>네트워크에 연결되어 사용 가능한 네트워크 인터페이스가 있으면 true, 그렇지 않으면 false가 반환된다.</returns>
		public static bool GetActiveIpAddress(out IPAddress activeAddress)
		{
			try
			{
				activeAddress = null;

				// 네트워크가 이용 불가능할 경우, IP 주소를 가져오지 못한다.
				if (!NetworkInterface.GetIsNetworkAvailable())
				{
					return false;
				}

				// 모든 네트워크 인터페이스 목록을 가져온다.
				var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

				foreach (var networkInterface in networkInterfaces)
				{
					// 네트워크 인터페이스 중 인터넷을 지원하고 연결되어 있는 네트워크 인터페이스를 대상으로 한다.
					if ((networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet ||
						networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet3Megabit ||
						networkInterface.NetworkInterfaceType == NetworkInterfaceType.FastEthernetFx ||
						networkInterface.NetworkInterfaceType == NetworkInterfaceType.FastEthernetT ||
						networkInterface.NetworkInterfaceType == NetworkInterfaceType.GigabitEthernet ||
						networkInterface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211) &&
						networkInterface.OperationalStatus == OperationalStatus.Up)
					{
						var ipProperties = networkInterface.GetIPProperties();

						// DNS에 표시될 수 있는 IP 주소를 가져온다.
						var unicastInformation = ipProperties.UnicastAddresses.FirstOrDefault(unicast => unicast.IsDnsEligible);

						if (unicastInformation != null)
						{
							activeAddress = unicastInformation.Address;

							return true;
						}
					}
				}
			}
			catch (Exception error)
			{
				throw error;
			}

			return false;
		}

		/// <summary>
		/// 사용 가능한 네트워크 어댑터들의 MAC 주소 목록을 가져온다.
		/// </summary>
		/// <param name="macAddresses">MAC 주소 목록을 참조한다.</param>
		/// <returns>MAC 주소 목록을 가져온 경우 true, 그렇지 못한 경우 false가 반환된다.</returns>
		public static bool GetMacAddress(out IList<string> macAddresses)
		{
			try
			{
				macAddresses = new List<string>();

				ObjectQuery query = new ObjectQuery("select * FROM Win32_NetworkAdapter where NetEnabled = 'true' and PhysicalAdapter = 'true'");

				ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
				
				foreach (ManagementObject managementObject in searcher.Get())
				{
					macAddresses.Add(managementObject["MACAddress"].ToString());
				}

				searcher.Dispose();

				if (macAddresses.Count < 1)
				{
					return false;
				}

				return true;
			}
			catch (Exception error)
			{
				throw error;
			}
		}
	}
}